#include<assert.h>
#include<string.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<sys/types.h>

#define LEFT "["
#define RIGHT "]"
#define LABLE "#"
#define DELIM " "
#define LINE_SIZE 1024
#define ARGC_SIZE 32
#define EXIT_CODE 44
#define PATH_SIZE 100

int quit=0;
int lastcode=0;
char CommandLine[LINE_SIZE];
char* argv[ARGC_SIZE];//存放命令行参数
char pwd[LINE_SIZE];
char* env[LINE_SIZE];
int envsize=0;

const char* get_user_name()
{
    return getenv("USER");
}

const char* get_host_name()
{
    return getenv("HOSTNAME");
}

void get_pwd()
{
    getcwd(pwd,sizeof(pwd));
}

int Interact(char* cline,int size)
{
    get_pwd();
    printf(LEFT"%s@%s %s"RIGHT""LABLE" ",get_user_name(),get_host_name(),pwd);    
    char* s = fgets(cline,size,stdin);
    assert(s!=NULL);
    (void)s;
    cline[strlen(cline)-1] = '\0';
}

int splitstring(char* commandline,char* _argv[])
{
    //分析命令行 command -> "ls -a -l -n\0"
    int i=0;
    _argv[i++]=strtok(commandline,DELIM);
    while(_argv[i++] = strtok(NULL,DELIM));
    return i-1;//命令行参数个数
}

void NormalExcute(char *_argv[])
{
     pid_t id = fork();
     if(id < 0)
     {
         perror("fork");
         return;
     }
     if(id == 0)
     {
         //子进程执行普通命令，进程程序替换
         execvp(_argv[0],_argv);
         exit(EXIT_CODE);
     }
     else
     {
         int status = 0;
         pid_t rid = waitpid(id, &status,0);
         if(rid == id)
         {
             //等待成功
             lastcode=WEXITSTATUS(status);
         }
     }
 
}

int bulidCommand(char* _argv[],int _argc)
{
    if(_argc == 2 && strcmp(_argv[0],"cd") == 0)
    {
        chdir(_argv[1]);
        get_pwd();
        sprintf(getenv("PWD"),"%s",pwd);
        return 1;
    }
    else if(_argc ==2 && strcmp(_argv[0],"export") == 0)
    {
        int realsize=(strlen(_argv[1]))+1;
        env[envsize]=(char*)malloc(realsize);
        memcpy(env[envsize], _argv[1], realsize);
        putenv(env[envsize++]);
        return 1;
    }
    else if(_argc == 2 && strcmp(_argv[0],"unset") == 0)
    {
        unsetenv(_argv[1]);
        return 1;
    }
    else if(_argc == 2 && strcmp(_argv[0],"echo")==0)
    {
        if(strcmp(_argv[1],"$?")==0)
        {
            printf("%d\n",lastcode);
            lastcode=0;
        }
        //打印环境变量
        else if(*_argv[1] == '$') 
       {
            char *val = getenv(_argv[1]+1);
            if(val)printf("%s\n",val);
       }
       //正常打印
       else
       {
            int lenth = strlen(_argv[1]);
            if(*_argv[1] == '"' && _argv[1][lenth-1] == '"')
            {
                _argv[1][lenth-1] = '\0';
                printf("%s\n",_argv[1]+1);
            }
            else printf("%s\n",_argv[1]);
       }
       return 1;
    }

    //ls的特殊着色处理
    if(strcmp(_argv[0],"ls")==0)
    {
        _argv[_argc++] = "--color";
        _argv[_argc] = NULL;
    }
    return 0;
}

int main()
{
    while(!quit)
    {
        //1.交互问题，获取命令行
        Interact(CommandLine,sizeof(CommandLine));
        

        //2.字符串分割
        int argc = splitstring(CommandLine,argv);
        if(argc==0)continue;

        //3.处理内置命令，父进程执行
        if(bulidCommand(argv,argc))continue;

        //4.处理普通命令，子进程执行
        NormalExcute(argv);       
        
    }
    return 0;
}
